//
//  SPTaggedTextView.m
//  Sophie
//
//  Created by Anton Chebotaev on 17/10/09.
//  Copyright 2009 IFMO. All rights reserved.
//

#import "SPTaggedTextView.h"

@interface SPTaggedTextView (Private)
- (void)coverSelectedTextWithBeginTag:(NSString *)bt endTag:(NSString *)et actionName:(NSString *)anActionName;

- (void)coverTextwithBeginTag:(NSString *)bt endTag:(NSString *)et atRange:(NSRange)range;
- (void)decoverTextwithBeginTag:(NSString *)bt endTag:(NSString *)et atRange:(NSRange)range;
	
- (void)startModalSheet:(NSWindow *)sheet;

@end

@implementation SPTaggedTextView

#pragma mark Life Cycle
- (void)encodeWithCoder:(NSCoder *)coder
{
    [super encodeWithCoder:coder];
}

- (id)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {
		[self setFont:[NSFont fontWithName:@"Monaco" size:11]];
		[ljuserNameField setDataSource:self];
		[NSBundle loadNibNamed: @"SPTaggedTextViewSheets" owner: self];
		[cutContentField setFont:[NSFont fontWithName:@"Monaco" size:11]];
    }
	return self;
}

#pragma mark Managing Pasteboard
- (NSArray *)readablePasteboardTypes
{
	//return [super readablePasteboardTypes]; //TODO: Review this
	return [NSArray arrayWithObjects:@"WebURLsWithTitlesPboardType", NSStringPboardType, NSURLPboardType, NSFilenamesPboardType, nil];
}

- (BOOL)readSelectionFromPasteboard:(NSPasteboard *)pboard type:(NSString *)type
{
	if([[pboard types] containsObject:@"WebURLsWithTitlesPboardType"])
	{
		// Review this safari hack
	    NSArray *pbArray = [pboard propertyListForType:@"WebURLsWithTitlesPboardType"];
	    NSArray *URLArray = [pbArray objectAtIndex:0];
		NSString *url, *title;
		
	    if(URLArray){
			url = [URLArray objectAtIndex:0];
	    }else{
			url = @"";
	    }
		
	    NSArray *titleArray = [pbArray objectAtIndex:1];
	    if(titleArray){
			title = [titleArray objectAtIndex:0];
	    }else{
			title = @"";
	    }
		
	    // just one of many fascinating uses!
	    NSString *replacement = [NSString stringWithFormat:@"<a href=\"%@\">%@</a>",url, title, title];
		[self insertText:replacement];
		return YES;
	}
	else
	{
		return [super readSelectionFromPasteboard:pboard type:type];
	}
	
	return NO;
}

#pragma mark IBAction
- (IBAction)bold:(id)sender
{
	[self coverSelectedTextWithBeginTag:@"<b>" endTag:@"</b>" actionName:@"Bold"];
}

- (IBAction)italic:(id)sender
{
	[self coverSelectedTextWithBeginTag:@"<i>" endTag:@"</i>" actionName:@"Italic"];
}


- (IBAction)underlined:(id)sender
{
	[self coverSelectedTextWithBeginTag:@"<u>" endTag:@"</u>" actionName:@"Underline"];
}

- (IBAction)strikethrough:(id)sender
{
	[self coverSelectedTextWithBeginTag:@"<s>" endTag:@"</s>" actionName:@"Strikethrough"];
}

- (IBAction)bigger:(id)sender
{
	[self coverSelectedTextWithBeginTag:@"<big>" endTag:@"</big>" actionName:@"Bigger Text"];
}


- (IBAction)smaller:(id)sender
{
	[self coverSelectedTextWithBeginTag:@"<small>" endTag:@"</small>" actionName:@"Smaller Text"];
}


- (IBAction)showColors:(id)sender
{
	//TODO: Implement this
}


- (IBAction)alignLeftTag:(id)sender
{
	[self coverSelectedTextWithBeginTag:@"<div align=left>" endTag:@"</div>" actionName:@"Align Left"];
}


- (IBAction)alignRightTag:(id)sender
{
	[self coverSelectedTextWithBeginTag:@"<div align=right>" endTag:@"</div>" actionName:@"Align Right"];
}


- (IBAction)alignCenterTag:(id)sender
{
	[self coverSelectedTextWithBeginTag:@"<center>" endTag:@"</center>" actionName:@"Align Center"];
}

#pragma mark Interface Tools
- (IBAction)insertHyperlink:(id)sender {
//	NSRange selectedRange = [[[self selectedRanges] objectAtIndex:0] rangeValue];
//	if (selectedRange.length != 0) {
//		[self coverSelectedTextWithBeginTag:@"<a href=\""
//									 endTag:@"\"></a>"
//								 actionName:@"Insert Hyperlink"];
//		return;
//	}
	
	NSString *URLFromPasteboard = [[NSPasteboard generalPasteboard] stringForType:NSStringPboardType];
	if(URLFromPasteboard.length != 0)
	{
		[linkURLField setStringValue:URLFromPasteboard];
	}
	
	[self startModalSheet: URLWindow];
}
- (IBAction)applyInsertHyperlink:(id)sender {
	NSString *text = [linkTitleField stringValue];
	NSString *url = [linkURLField stringValue]; 
	NSString *alt = [linkAltField stringValue]; 
	
	if ([alt length] > 0) {
		[self insertText:[NSString stringWithFormat:@"<a href=\"%@\" alt=\"%@\">%@</a>", url, alt, text]];
	} else {
		[self insertText:[NSString stringWithFormat:@"<a href=\"%@\">%@</a>", url, text]];
	}
	if (![[self undoManager] isUndoing]) {
		[[self undoManager] setActionName:@"Insert Hyperlink"];
	}	
	
	[linkTitleField setStringValue:@""];
	[linkURLField setStringValue:@""];
	[linkAltField setStringValue:@""];
	[self stopModalSheet:sender];
}

- (IBAction)insertLJCut:(id)sender {
	NSString *URLFromPasteboard = [[NSPasteboard generalPasteboard] stringForType:NSStringPboardType];
	if(URLFromPasteboard.length != 0)
	{
		[cutContentField setString:URLFromPasteboard];
	}
	
	[self startModalSheet: cutWindow];
}
- (IBAction)applyInsertLJCut:(id)sender {
	NSString *title = [cutTitleField stringValue];
	NSString *content = [cutContentField string]; 
	
	if ([title length] > 0) {
		[self insertText:[NSString stringWithFormat:@"<lj-cut text=\"%@\">%@</lj-cut>", title, content]];
	} else {
		[self insertText:[NSString stringWithFormat:@"<lj-cut>%@</lj-cut>", content]];
	}
	if (![[self undoManager] isUndoing]) {
		[[self undoManager] setActionName:@"Insert Cut"];
	}	
	
	[cutTitleField setStringValue:@""];
	[cutContentField setString:@""];
	[self stopModalSheet:sender];
}

- (IBAction)insertLJUser:(id)sender {
	[self startModalSheet: ljuserWindow];
}
- (IBAction)applyInsertLJUser:(id)sender {
	NSString *content = [ljuserNameField stringValue]; 
	[self insertText:[NSString stringWithFormat:@"<lj user=\"%@\">", content]];
	if (![[self undoManager] isUndoing]) {
		[[self undoManager] setActionName:@"Insert Link to Journal"];
	}		
	[ljuserNameField setStringValue:@""];
	[self stopModalSheet:sender];
}

- (IBAction)insertPicture:(id)sender {
	NSRange selectedRange = [[[self selectedRanges] objectAtIndex:0] rangeValue];
	if (selectedRange.length != 0) {
		[self coverSelectedTextWithBeginTag:@"<img src=\""
									 endTag:@"\"/>"
								 actionName:@"Insert Picture"];
		return;
	}
	
	NSString *URLFromPasteboard = [[NSPasteboard generalPasteboard] stringForType:NSStringPboardType];
	if(URLFromPasteboard.length != 0)
	{
		[imageURLField setStringValue:URLFromPasteboard];
	}
	
	[self startModalSheet: pictureWindow];
}
- (IBAction)applyInsertPicture:(id)sender {
	NSString *url = [imageURLField stringValue];
	NSString *alt = [imageAltField stringValue]; 
	
	if ([alt length] > 0) {
		[self insertText:[NSString stringWithFormat:@"<img src=\"%@\" alt=\"%@\"/>", url, alt]];
	} else {
		[self insertText:[NSString stringWithFormat:@"<img src=\"%@\"/>", url]];
	}
	if (![[self undoManager] isUndoing]) {
		[[self undoManager] setActionName:@"Insert Picture"];
	}	

	[imageURLField setStringValue:@""];
	[imageAltField setStringValue:@""];
	[self stopModalSheet:sender];
}

- (void)coverTextwithBeginTag:(NSString *)bt endTag:(NSString *)et atRange:(NSRange)range {
	NSString *input = [[self string] substringWithRange:range];
	NSString *result;
	result = [NSString stringWithFormat:@"%@%@%@", bt, input, et];
	[self replaceCharactersInRange:range withString: result];	
	
	NSRange newRange = range;
	newRange.location += [bt length];
	[[[self undoManager] prepareWithInvocationTarget:self] decoverTextwithBeginTag:bt endTag:et atRange:newRange];
}

- (void)decoverTextwithBeginTag:(NSString *)bt endTag:(NSString *)et atRange:(NSRange)range {
	NSRange deleteRange = range;
	deleteRange.location -= [bt length];
	deleteRange.length = [bt length];
	[self replaceCharactersInRange:deleteRange withString:@""];
	
	deleteRange.location += range.length;
	deleteRange.length = [et length];	
	[self replaceCharactersInRange:deleteRange withString:@""];
	
	NSRange newRange = range;
	newRange.location -= [bt length];
	[[[self undoManager] prepareWithInvocationTarget:self] coverTextwithBeginTag:bt endTag:et atRange:newRange];
}


- (void)coverSelectedTextWithBeginTag:(NSString *)bt
							   endTag:(NSString *)et 
						   actionName:(NSString *)anActionName
{
	NSArray *selectionRanges = [self selectedRanges];
	NSMutableArray *newRanges = [NSMutableArray array];
	
	int shift = 0;

	for (NSValue *range in selectionRanges)
	{
		// Shifting focus for the length of "<tag></tag>"
		NSRange convertedInsertRange = [range rangeValue];
		convertedInsertRange.location += shift * ([bt length] + [et length]);
		
		// Cover text and add undo operation title
		[self coverTextwithBeginTag:bt endTag:et atRange:convertedInsertRange];		
		if (![[self undoManager] isUndoing]) {
			[[self undoManager] setActionName:anActionName];
		}	

		// Add converted selection range to array
		NSRange convertedSelectRange = convertedInsertRange;
		convertedSelectRange.length += [bt length] + [et length];
		
		NSValue *newRange = [NSValue valueWithRange:convertedSelectRange];
		[newRanges addObject:newRange];
		
		// increase shift counter
		shift++;
	}
	[self setSelectedRanges:newRanges];
}

- (void)startModalSheet:(NSWindow *)sheet
{
    currentSheet = sheet;
    [NSApp beginSheet: currentSheet
       modalForWindow: [self window]
        modalDelegate: nil
       didEndSelector: nil
          contextInfo: nil];
}

- (IBAction)stopModalSheet:(id)sender
{
    [NSApp endSheet: currentSheet];
    [currentSheet orderOut: nil];
    currentSheet = nil;
}

#pragma mark Delegate for username NSComboBox
- (void)setAccount:(LJAccount *)anAccount {
	[ljuserNameField removeAllItems];
	
	NSMutableArray *newItems = [NSMutableArray array];
	for(LJFriend *friend in [anAccount friends]){
		if ([friend type] == LJPerson) {
			[newItems addObject:[friend username]];
		}
	}	
	[newItems sortUsingSelector:@selector(caseInsensitiveCompare:)];
	
	[ljuserNameField addItemsWithObjectValues:newItems];
}
@end
